<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as d3 from 'd3'

const svg = ref(null)

onMounted(() => {
  window.addEventListener('resize', setTime)
  setTime()
})
onUnmounted(() => {
  window.removeEventListener('resize', setTime)
})

const setTime = () => {
  setTimeout(() => {
    draw()
  })
}

const draw = () => {
  // 获取容器元素，并获取宽高
  const box = document.getElementById('main')
  const height = box.clientHeight
  const width = box.clientWidth
  const margin = {
    top: 40,
    bottom: 40,
    left: 60,
    right: 40
  }
  const innerWidth = width - margin.left - margin.right
  const innerHeight = height - margin.top - margin.bottom
  // 渲染的数据
  const data = [
    { label: 'Mon', value: 10 },
    { label: 'Tue', value: 52 },
    { label: 'Wed', value: 200 },
    { label: 'Thu', value: 334 },
    { label: 'Fri', value: 390 },
    { label: 'Sat', value: 330 },
    { label: 'Sun', value: 220 }
  ]

  if (!svg.value) {
    // 创建容器
    svg.value = d3.select('#main').append('svg').attr('height', height).attr('width', width).attr('viewBox', [0, 0, width, height])
  } else {
    // 使用容器
    svg.value.attr('width', width).attr('height', height).attr('viewBox', [0, 0, width, height])
    // 绘制前清空
    svg.value.selectAll('*').remove()
  }
  const yMax = Math.floor(Math.ceil(d3.max(data, d => d.value) / 100) * 100)
  const xScale = d3
    .scaleBand()
    .domain(data.map(d => d.label))
    .range([0, innerWidth])
  const yScale = d3.scaleLinear().domain([0, yMax]).range([innerHeight, 0])

  // 创建柱子
  svg.value
    .selectAll('g')
    .data(data)
    .enter()
    .append('g')
    .attr('class', 'bar')
    .attr('transform', d => `translate(${xScale(d.label) + margin.left}, ${margin.top})`)
    .selectAll('rect')
    .data(d => [d.value, d.value]) // 创建两个矩形元素
    .enter()
    .append('rect')
    .attr('class', (_, i) => (i === 0 ? 'back' : 'content'))
    .attr('x', (_, i) => (i === 0 ? 0 : xScale.bandwidth() * 0.2))
    .attr('y', (d, i) => (i === 0 ? 0 : yScale(d)))
    .attr('width', (_, i) => (i === 0 ? xScale.bandwidth() : xScale.bandwidth() * 0.6))
    .attr('height', (d, i) => (i === 0 ? innerHeight : innerHeight - yScale(d)))
    .style('fill', (d, i) => (i === 0 ? 'transparent' : '#5470C6')) // 底部矩形和特殊效果矩形的颜色

  // 添加交互效果
  d3.selectAll('.bar')
    .on('mouseover', function () {
      d3.select(this).select('.back').style('fill', '#F6F8FC')
      d3.select(this).select('.content').style('fill', '#748EDE')
    })
    .on('mouseout', function () {
      d3.select(this)
        .selectAll('rect')
        .style('fill', (d, i) => (i === 0 ? 'transparent' : '#5470C6')) // 鼠标移出时恢复颜色
    })

  // 添加 x 轴和 y 轴
  const xAxis = d3.axisBottom(xScale)
  const yAxis = d3.axisLeft(yScale)

  svg.value
    .append('g')
    .attr('class', 'x-axis')
    .attr('transform', `translate(${margin.left}, ${innerHeight + margin.top})`)
    .call(xAxis)

  svg.value.append('g').attr('class', 'y-axis').attr('transform', `translate(${margin.left}, ${margin.top})`).call(yAxis)
}
</script>

<template>
  <div class="page1">
    <div class="header">
      <h1>柱状图</h1>
    </div>
    <div id="main" class="main"></div>
  </div>
</template>

<style lang="scss" scoped>
.page1 {
  position: relative;
  height: 100%;
  width: 100%;
  overflow: hidden;
  .header {
    margin-left: 20px;
    line-height: 60px;
  }
  .main {
    height: calc(100% - 60px);
  }
}
</style>
